﻿using System;
using System.Collections;
using System.Text;
using System.Net;
using System.Web;
using System.IO.Compression;
using System.IO;
using System.Text.RegularExpressions;
using MediaPortal.GUI.Library;
using MediaPortal.Profile;

namespace MyLeech.Sites
{
  class HTTP_Common
  {

    public string Fetch_HTML(string searchurl,string referer)
    {
      try
      {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(searchurl);
        request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 1.1.4322)"; //honest, we are IE
        request.KeepAlive = false;
        request.Referer = referer; //we were refered by binsearch.info
        request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate"); //add gzip accept    

        HttpWebResponse WebResponse = (HttpWebResponse)request.GetResponse();

        System.IO.Stream responseStream = responseStream = WebResponse.GetResponseStream();
        if (WebResponse.ContentEncoding.ToLower().Contains("gzip"))
          responseStream = new GZipStream(responseStream, CompressionMode.Decompress);
        else if (WebResponse.ContentEncoding.ToLower().Contains("deflate"))
          responseStream = new DeflateStream(responseStream, CompressionMode.Decompress);

        System.IO.StreamReader Reader = new System.IO.StreamReader(responseStream, Encoding.Default);

        string HTML = Reader.ReadToEnd();
        Reader.Close();
        responseStream.Close();
        WebResponse.Close();

        return (HTML);
      }
      catch (Exception ex)
      {
        //bastard

        Log.Info("Data: " + ex.Data);
        Log.Info("HelpLink: " + ex.HelpLink);
        Log.Info("InnerException: " + ex.InnerException);
        Log.Info("Message: " + ex.Message);
        Log.Info("Source: " + ex.Source);
        Log.Info("StackTrace: " + ex.StackTrace);
        Log.Info("TargetSite: " + ex.TargetSite);
        return "";

      }
    }
    // Snippet http://csharpfeeds.com/post/5518/HttpWebRequest_and_GZip_Http_Responses.aspx
    // with a few modifications.
    public bool FETCH_NZB(string NZB_URL, string REFERER, string METHOD, string PostData, string Keyword)
    {
      // connect with the update page
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(NZB_URL);

      request.ServicePoint.Expect100Continue = false; //to avoid Expectation errors
      request.Accept = "text/xml"; //we will accept your XML, yes sir.
      request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 1.1.4322)"; //honest, we are IE
      request.AllowAutoRedirect = false; //Auto redirect
      request.ContentType = "application/x-www-form-urlencoded"; //this content is of type
      request.Referer = REFERER; //we were refered by...
      request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate"); //add gzip accept

      if (!string.IsNullOrEmpty(PostData)) //Post Data?
      {
        request.Method = METHOD; //Set METHOD as Post
        byte[] lbPostBuffer = Encoding.Default.GetBytes(PostData); //Get Content Size

        request.ContentLength = lbPostBuffer.Length; //Find length

        System.IO.Stream PostStream = request.GetRequestStream(); //Request
        PostStream.Write(lbPostBuffer, 0, lbPostBuffer.Length); //Write POST request
        PostStream.Close(); //Close stream
      }
      HttpWebResponse WebResponse = (HttpWebResponse)request.GetResponse(); //get the response

      //GZIP DECODING
      System.IO.Stream responseStream = responseStream = WebResponse.GetResponseStream();
      if (WebResponse.ContentEncoding.ToLower().Contains("gzip"))
        responseStream = new GZipStream(responseStream, CompressionMode.Decompress);
      else if (WebResponse.ContentEncoding.ToLower().Contains("deflate"))
        responseStream = new DeflateStream(responseStream, CompressionMode.Decompress);

      System.IO.StreamReader Reader = new System.IO.StreamReader(responseStream, Encoding.Default);
      //Write response into string
      string NZB = Reader.ReadToEnd();

      WebResponse.Close(); //close conection
      responseStream.Close(); //close connection
      if (NZB.IndexOf("Error: ", 0, 7) > -1) { return false; } //if error found return false
      else if (NZB.Length > 0) //else if string greater than 0 and we're still here
      {
        //WRITE FILE. Load settings, get hella location, write NZB
        Settings mpSettings = new Settings(MediaPortal.Configuration.Config.GetFolder(MediaPortal.Configuration.Config.Dir.Config) + @"\MyLeech.xml");
        if (mpSettings.GetValueAsString("#Hellanzb", "location", "null").Length < 5) { return false; } //no hella, return
        string File_Name = String.Empty;
        string Hell_Location = mpSettings.GetValueAsString("#Hellanzb", "location", "null") + @"\";
        if (System.IO.File.Exists(Hell_Location + Keyword + ".nzb"))
        {
          Random RandomClass = new Random(); //file exists, add random number
          File_Name = Hell_Location + Keyword + RandomClass.Next(4, 14) + ".nzb";
        }
        else { File_Name = Hell_Location + Keyword + ".nzb"; }
        System.IO.TextWriter tw = new System.IO.StreamWriter(File_Name);
        // write a line of text to the file
        tw.Write(NZB);
        // close the stream
        tw.Close();
        mpSettings.Dispose();
      }
      
      return true;

    }
    //**************************************************
    //------------CHECK INTERNET CONNECTION----------
    //Can be used outside of binsearch.cs
    //working function will be called before attempting to obtain search results.
    public static bool ConnectionExists()
    {
      try
      {
        System.Net.Sockets.TcpClient clnt = new System.Net.Sockets.TcpClient("www.google.com", 80);
        clnt.Close();
        return true;
      }
      catch (Exception)
      {
        return false;
      }
    }
   
    public string[] Filters(string filter_string)
    {
      int NumberOfOccurances = 0;
      char[] OrginalChars = filter_string.ToCharArray();

      for (int i = 0; i < OrginalChars.Length; i++)
      {
        if (OrginalChars[i].Equals(";")) { NumberOfOccurances++; }
      }
      string[] arInfo = new string[(NumberOfOccurances + 1)];
      // define which character is seperating fields
      char[] splitter = { ';' };
      arInfo = filter_string.Split(splitter);
      return arInfo;
    }
    public string Clean_Name(string Name)
    {
      int start = 0;
      int end = 0;
      if (Name.Length < 5) {return Name;} // its crap, take it back
      if (Name.IndexOf("\"", 0, Name.Length) > -1)
      {//results are very difficult to read without this
        //just extracts a string between one " and another i.e "string"
        start = Name.IndexOf('"') + 1;
        if ((Name.Substring(start, 1)) == "\"") { return Name; } //if "" default
        else //else "<name>" exists
        {
          end = Name.IndexOf('"', start);
          string sub = Name.Substring(start, end - start);
          if (sub.Length < 21) { return Name; } //because some people don't follow rules!
          else { return sub; } //
        }
      }
      else { return Name; }
    }
    public bool Remove_Auto_Filter(string Name,string[] Remove_Filters)
    {
      string FILTER = String.Empty;
      for (int i = 0; i < Remove_Filters.Length; i++) { //build filter regex
        if (Remove_Filters[i] == String.Empty) { continue; }
        if (i == 0) { FILTER = FILTER + Remove_Filters[i]; }
        else { FILTER = FILTER + "|" + Remove_Filters[i]; }
      }//end for
      
      if (FILTER.Length > 3)
      {
        if (Regex.IsMatch(@Name, @"([\.\s-\+]?" + FILTER + @"[\.\s-\+]?)", RegexOptions.IgnoreCase | RegexOptions.Multiline))
        {
          return true;
        }
        else
        {
          return false;
        }
      }
      else
      {
        return false;
      }
    }

    //Regex function to release all grouped matches
    public ArrayList ExtractGroupings(string source,
   string matchPattern, bool wantInitialMatch)
    {
      ArrayList keyedMatches = new ArrayList();
      int startingElement = 1;
      if (wantInitialMatch)
      {
        startingElement = 0;
      }
      try
      {
        Regex RE = new Regex(matchPattern, RegexOptions.Multiline | RegexOptions.IgnoreCase);
        MatchCollection theMatches = RE.Matches(source);
        foreach (Match m in theMatches)
        {
          Hashtable groupings = new Hashtable();
          for (int counter = startingElement;
             counter < m.Groups.Count; counter++)
          {
            // If we had just returned the MatchCollection directly, the
            // GroupNameFromNumber method would not be available to use
            groupings.Add(RE.GroupNameFromNumber(counter),
            m.Groups[counter]);
          }
          keyedMatches.Add(groupings);
        }
      }
      catch (Exception ex)
      {
        Log.Info("Data: " + ex.Data);
        Log.Info("HelpLink: " + ex.HelpLink);
        Log.Info("InnerException: " + ex.InnerException);
        Log.Info("Message: " + ex.Message);
        Log.Info("Source: " + ex.Source);
        Log.Info("StackTrace: " + ex.StackTrace);
        Log.Info("TargetSite: " + ex.TargetSite);
        return new ArrayList();
      }
      return (keyedMatches);
    }

  }
}
